package com.kedacom.ctsp.authz.security.controller;

import com.kedacom.ctsp.authz.AuthenticationService;
import com.kedacom.ctsp.authz.entity.AuthResource;
import com.kedacom.ctsp.authz.entity.AuthUser;
import com.kedacom.ctsp.authz.entity.Authentication;
import com.kedacom.ctsp.authz.exception.UnauthorizedException;
import com.kedacom.ctsp.authz.security.captcha.CaptchaProperties;
import com.kedacom.ctsp.authz.security.captcha.CaptchaService;
import com.kedacom.ctsp.authz.security.provider.TokenBean;
import com.kedacom.ctsp.authz.security.provider.TokenManager;
import com.kedacom.ctsp.authz.security.util.AccessLoggerConstant;
import com.kedacom.ctsp.lang.exception.CommonException;
import com.kedacom.ctsp.logging.AccessLogger;
import com.kedacom.ctsp.web.controller.message.ResponseMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.xml.bind.ValidationException;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.Set;
import java.util.stream.Collectors;

import static com.kedacom.ctsp.web.controller.message.ResponseMessage.ok;

/**
 * 登录权限相关
 *
 * @author sunchenjie
 * @create 2017-12-28 13:20
 **/
@RequestMapping("${ctsp.web.mappings.authority.authorize:auth}")
@AccessLogger(AccessLoggerConstant.Module.AUTH)
@Api(tags = "rbac-authz", description = "提供基本的授权功能")
@ResponseBody
@Slf4j
public class AuthorizationController {

    public static final String CAPTCHA_IMAGE_FORMAT = "jpeg";
    @Autowired(required = false)
    private CaptchaService captchaService;
    @Autowired
    private CaptchaProperties captchaProperties;
    @Autowired
    private TokenManager tokenManager;

    @Autowired
    protected AuthenticationService authenticationService;

    public AuthorizationController() {
        ImageIO.setUseCache(false);
    }


    @GetMapping("/captcha/show")
    @ApiOperation("获取验证码")
    public ResponseMessage<Boolean> showCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (captchaService != null && !captchaService.checkWrongTimes(request, captchaProperties.getShowTimes())) {
            return ok(true);
        } else {
            return ok(false);
        }
    }

    @GetMapping("/captcha")
    @ApiOperation("获取验证码")
    public void captcha(HttpServletRequest request, HttpServletResponse response) throws IOException {

        // 未开启验证码功能的时候，captchaService不会成功注入
        if (captchaService == null) {
            throw new CommonException("没有开启验证码功能 或 没有对应的处理类");
        }

        // flush it in the response
        response.setHeader("Cache-Control", "no-store");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/" + CAPTCHA_IMAGE_FORMAT);

        String capText = captchaService.createText();
        log.info("session: " + request.getSession().getId());
        log.info("验证码文字: " + capText);
        BufferedImage image = captchaService.createImage(capText);
        ServletOutputStream out = response.getOutputStream();
        try {
            captchaService.setSessionValue(request.getSession(), capText, new Date());
        } catch (Exception e) {
            log.error("获取验证码错误：", e);
        }
        ImageIO.write(image, CAPTCHA_IMAGE_FORMAT, out);

    }

    @GetMapping("/me")
    @AccessLogger("当前登录用户权限信息")
    @ApiOperation("当前登录用户权限信息")
    public ResponseMessage<Authentication> me() {
        Authentication authentication = Authentication.current().orElseThrow(UnauthorizedException::new);

        return ok(authentication);
    }

    @GetMapping("/resourceSigns")
    @AccessLogger("获取当前登录用户资源标识")
    @ApiOperation("获取当前登录用户资源标识")
    public ResponseMessage<Set<String>> getResourceSigns() {
        Authentication authentication = Authentication.current().orElseThrow(UnauthorizedException::new);
        //通过接口获取，获取资源
        Set<AuthResource> myResources = authenticationService.getAuthResource(authentication);
        Set<String> resourceSigns = myResources.stream().map(AuthResource::getSign).collect(Collectors.toSet());
        return ok(resourceSigns);
    }

    @GetMapping("/resources")
    @AccessLogger("获取当前登录用户资源")
    @ApiOperation("获取当前登录用户资源")
    public ResponseMessage<Set<AuthResource>> getResources() {
        Authentication authentication = Authentication.current().orElseThrow(UnauthorizedException::new);
        //通过接口获取，获取资源
        Set<AuthResource> myResources = authenticationService.getAuthResource(authentication);
        return ok(myResources);
    }

    @GetMapping("/roleSigns")
    @AccessLogger("获取当前登录用户角色标识")
    @ApiOperation("获取当前登录用户角色标识")
    public ResponseMessage<Set<String>> getRoleSigns() {
        Authentication authentication = Authentication.current().orElseThrow(UnauthorizedException::new);
        return ok(authentication.getRoleSigns());
    }

    @PostMapping("/login_token")
    @AccessLogger("免密登录")
    @ApiOperation("免密登录")
    public ResponseMessage<AuthUser> loginByToken(@Valid @RequestBody TokenBean tokenBean) {
        return ok(tokenManager.login(tokenBean.getUsername(), tokenBean.getAccessToken(), tokenBean.getAuth()));
    }

    @GetMapping("/token_info")
    @AccessLogger("根据token获取信息")
    @ApiOperation("根据token获取信息")
    public ResponseMessage<TokenBean> getTokenInfo(HttpServletRequest httpServletRequest) throws ValidationException {
        String token = httpServletRequest.getHeader("token");
        if (StringUtils.isBlank(token)) {
            throw new ValidationException("token必填");
        }
        TokenBean tokenBean = new TokenBean();
        tokenBean.setAccessToken(tokenManager.getAccessTokenByToken(token));
        tokenBean.setUsername(tokenManager.getUsernameByToken(token));
        return ok(tokenBean);
    }

    @GetMapping("/unauthorized")
    @AccessLogger("未授权")
    @ApiOperation("未授权")
    public ResponseMessage unauthorized(HttpServletRequest request) {
        ResponseMessage responseMessage = ResponseMessage.ok();
        if (Authentication.current().isPresent()) {
            responseMessage.setCode(HttpStatus.OK.toString());
            responseMessage.setMessage("ok");
        } else {
            responseMessage.setCode(HttpStatus.UNAUTHORIZED.toString());
            responseMessage.setMessage(request.getContextPath());
        }


        return responseMessage;
    }
}
